import $, * as Utils from './modules/tools'
import * as Draw from './modules/draw'
import FileHandler from './modules/filesHandler'

// 获取canvas工具链
const container = document.querySelector('.scroll_box'),
    canvas = document.querySelector('#clipCanvas'),
    ctx = canvas.getContext('2d');
Draw.canvasOptimize(canvas, ctx);

//#region ----------------------- 处理文件上传回显功能
// 处理拖拽上传
let dropBox = document.querySelector('#dropBox');
dropBox.addEventListener('dragenter', function (e) { e.preventDefault() });
dropBox.addEventListener('dragover', function (e) { e.preventDefault() });
dropBox.addEventListener('drop', function drop(e) {
    e.stopPropagation(); //阻止事件冒泡
    e.preventDefault();//阻止默认事件 (上面的都一样)
    //拿到拖拽的文件
    let file = e.dataTransfer.files
    //调用函数传递文件的内容,然后进行解析转化为bas64格式的内容
    FileHandler(file, canvas, ctx, clipHandler);
})


// 处理手动选择文件
document.querySelector('#upload').onchange = function () {
    FileHandler(this.files, canvas, ctx, clipHandler)
}

function clipHandler() {
    $('.upload_container').hide();
    $('.clip_container').show();
    Utils.scrollView('.clip_container');
}
//#endregion ----------------------- 文件上传回显功能结束


//#region ----------------------- 按钮事件： 重置；重选；导出
// 重置切图区域
document.querySelector('#reset').onclick = function (e) {
    $('.canvas_box').remove('span');
    lineEditor.lineManger.clear();
}
// 重新选择图片
document.querySelector('#restart').onclick = function (e) {
    document.querySelector('#reset').click();

    $('.upload_container').show();
    $('.clip_container').hide();
}
// 确认导出
document.querySelector('#export').onclick = function (e) {

}
//#endregion ----------------------- 按钮事件结束


//#region  ----------------------- 辅助线相关功能开始：事件绑定，辅助线管理
const lineEditor = {
    isMove: false,
    rowClass: 'clip_line row_line',
    colClass: 'clip_line col_line',
    /** true 横线  false 纵向 */
    isRowLine: null,
    canvasBox: document.querySelector('.canvas_box'),
    currentLine: null,
    lineIndex: 1,
    maxOffset: {
        minSpace: 4, // 保留4px的边距
        top: null,
        left: null
    },
    init() {
        this.maxOffset.top = lineEditor.canvasBox.offsetHeight;
        this.maxOffset.left = lineEditor.canvasBox.offsetWidth;

        this.observer(lineEditor.canvasBox);

        this.bindEvents()
    },
    /**
     * 绑定事件
     */
    bindEvents() {
        //#region  从标尺区域新建辅助线

        // 禁用默认的拖拽事件
        document.querySelector('.clip_left').ondragstart = (e) => e.preventDefault();

        document.querySelector('.clip_left').onmousedown = function (e) {
            if (e.target.id == 'topArea' || e.target.id == 'leftArea') {
                // 必须先有一条横向辅助线
                if (e.target.id == 'leftArea' && lineEditor.canvasBox.querySelectorAll('.row_line').length == 0) return;

                lineEditor.isMove = true;

                lineEditor.isRowLine = e.target.id == 'topArea';

                lineEditor.currentLine = lineEditor.lineManger.create(lineEditor.isRowLine);
                lineEditor.currentLine.classList.add('line_edit_status');

                lineEditor.canvasBox.appendChild(lineEditor.currentLine);

                // 最近的两条线
                let nearLine = lineEditor.lineManger.findClosestOnAxis(lineEditor.isRowLine, lineEditor.isRowLine ? e.offsetX : e.offsetY);
                const attr = !lineEditor.isRowLine ? 'top' : 'left';
                // 计算两条线的间距来决定当前新建辅助线的长度与定位;
                var spacing = nearLine[1][attr] - nearLine[0][attr];
                lineEditor.currentLine.style[lineEditor.isRowLine ? 'width' : 'height'] = spacing + 'px';
                lineEditor.currentLine.style[attr] = nearLine[0][attr] + 'px';

                // FIXME 纵向123条线时当前新建线的定位不准确 应为3到右边界 实际定位到了左边界  长度好像没问题 原因可能是二次更新时导致的
            }
        }
        document.querySelector('.scroll_box').onmousemove = function (e) {
            if (e.target.className.indexOf('clip_line') !== -1) {
                return;// 阻止事件冒泡带来的影响
            }
            if (!lineEditor.isMove) return;
            if (lineEditor.isRowLine) {
                // 极限值的判断
                let top = e.offsetY;
                if (top <= lineEditor.maxOffset.minSpace) {
                    top = lineEditor.maxOffset.minSpace
                } else if (top >= lineEditor.maxOffset.top - lineEditor.maxOffset.minSpace) {
                    top = lineEditor.maxOffset.top - lineEditor.maxOffset.minSpace
                }
                lineEditor.currentLine.style.top = top + 'px';
            } else {
                let left = e.offsetX;
                if (left <= lineEditor.maxOffset.minSpace) {
                    left = lineEditor.maxOffset.minSpace
                } else if (left >= lineEditor.maxOffset.left - lineEditor.maxOffset.minSpace) {
                    left = lineEditor.maxOffset.left - lineEditor.maxOffset.minSpace
                }
                lineEditor.currentLine.style.left = left + 'px';
            }
        }
        document.querySelector('.scroll_box').onmouseleave = function (e) {
            lineEditor.isMove = false;
        }
        document.querySelector('.clip_left').onmouseup = function (e) {
            lineEditor.currentLine && lineEditor.currentLine.classList.remove('line_edit_status');
            lineEditor.isMove = false;
            lineEditor.currentLine = null;
        }
        document.querySelector('.clip_left').onmouseleave = function (e) {
            lineEditor.isMove = false;
        }
        //#endregion 从标尺区域新建辅助线

        //#region 二次编辑辅助线
        document.querySelector('.scroll_box').onmousedown = function (e) {
            if (e.target.className.indexOf('clip_line') !== -1) {
                lineEditor.currentLine = e.target;
                lineEditor.isMove = true;
                e.target.classList.add('line_edit_status');
                lineEditor.isRowLine = e.target.className.indexOf(lineEditor.rowClass) !== -1;
            }
        }
        document.querySelector('.scroll_box').onmouseup = function (e) {
            if (lineEditor.isMove) {
                lineEditor.isMove = false;
                lineEditor.currentLine.classList.remove('line_edit_status');
                lineEditor.currentLine = null;
            }
        }
        document.querySelector('.scroll_box').oncontextmenu = function (e) {
            if (e.target.className.indexOf('clip_line') !== -1) {
                let flag = window.confirm('是否删除此辅助线');
                flag && e.target.parentNode.removeChild(e.target);
            }
        }
        //#endregion
    },
    /**
     * 属性变动监听
     * 通过observer来进行移动与更新的解耦
     * @param {Element} targetNode
     */
    observer(targetNode) {
        // 观察器的配置（需要观察什么变动）
        const config = {
            subtree: true,
            childList: true,
            attributeFilter: ['style'],
        };

        // 当观察到变动时执行的回调函数
        const callback = function (mutationsList, observer) {
            // 遍历所有变动
            for (let mutation of mutationsList) {
                if (mutation.type === 'childList') { // 子节点的修改
                    if (mutation.addedNodes.length) {
                        lineEditor.lineManger.add(mutation.addedNodes[0])
                    } else if (mutation.removedNodes.length) {
                        lineEditor.lineManger.remove(mutation.removedNodes[0])
                    }
                }
                if (mutation.type === 'attributes') { // 属性的修改
                    lineEditor.lineManger.update(mutation.target);
                }
            }
        };

        // 创建一个观察器实例并传入回调函数
        const observer = new MutationObserver(callback);

        // 以上面的配置开始观察目标节点
        observer.observe(targetNode, config);
    },
    /**
     * 辅助线管理器
     *
     * 定义辅助线包装对象
     * @typeof {Object} Line
     * @property {Element} element 辅助线元素
     * @property {Number} top 辅助线top
     * @property {Number} left 辅助线left
     * @property {Array<Element>} intersect
     */
    lineManger: {
        lineList: {
            'row': [],
            'col': []
        },
        /**
         * 创建一条辅助线
         * @param {Boolean} type 线类型 true横向 false纵向
         * @returns
         */
        create(type) {
            let span = document.createElement('span');
            span.className = lineEditor.isRowLine ? lineEditor.rowClass : lineEditor.colClass;

            span.classList.add('current' + lineEditor.lineIndex);

            span.type = type ? 'row' : 'col';

            lineEditor.lineIndex++;

            return span;
        },
        /**
         * 向管理器中添加辅助线
         * @param {Element} element 要添加的元素
         */
        add(element) {
            const pack = {
                element: element,
                type: element.type,
                top: element.offsetTop,
                left: element.offsetLeft,
                intersect: lineEditor.lineManger.checkAllIntersect(element)
            }

            this.lineList[element.type].push(pack);

            return pack;
        },
        /**
         * 移除辅助线
         * @param {*} element
         */
        remove(element) {
            this.lineList[element.type] = this.lineList[element.type].filter(item => item.element !== element);
        },
        /**
         * 更新辅助线数据与样式
         * @param {*} element
         */
        update(element) {
            const index = this.lineList[element.type].findIndex(item => item.element === element);

            if (index !== -1) {
                // 更新线的数据
                let value = this.lineList[element.type][index];
                value.top = element.offsetTop;
                value.left = element.offsetLeft;
                value.intersect = lineEditor.lineManger.checkAllIntersect(element);
                // console.log(value.intersect);
                // 更新线的样式
                const _attr = value.type === 'row' ? 'left' : 'top';
                let spacing = value.intersect[1][_attr] - value.intersect[0][_attr];
                lineEditor.currentLine.style[value.type === 'row' ? 'width' : 'height'] = spacing + 'px';
                // lineEditor.currentLine.style[_attr] = value.intersect[0][_attr] + 'px';
            }
        },
        /**
         * 清空辅助线管理器
         */
        clear() {
            this.lineList = {
                'row': [],
                'col': []
            };
        },
        /**
         * 在创建时寻找在坐标轴上垂直方向最近的两条辅助线并返回差值，用来确认创建线的长度
         * @param {*} attr 要对比的属性，例如top，left
         * @param {*} offset 当前辅助线的偏移量
         */
        findClosestOnAxis(attr, offset) {
            const _attr = !lineEditor.isRowLine ? 'top' : 'left';
            // 先寻找起点连接在坐标轴上的线
            let closest = lineEditor.lineManger.lineList[_attr == 'top' ? 'row' : 'col'].filter((start) => start[lineEditor.isRowLine ? 'top' : 'left'] === 0);
            // 大小排序(体现在坐标轴上就是按离原点的远近排序)
            closest = closest.toSorted((a, b) => a[_attr] - b[_attr]);

            if (!closest.length) { // 不存在相邻线就直接返回极限值
                return [{ [_attr]: 0 }, { [_attr]: lineEditor.maxOffset[_attr] }];
            }

            let result,
                // 先找到最近一条线的索引值作为标定来进行后续的寻线
                index = closest.findIndex(item => item[_attr] >= offset);

            if (index === 0) { // 小于数组中的最小值，返回最小值跟极限min值
                result = [{ [_attr]: 0 }, closest[0]];
            } else if (index === -1) { // 大于数组中的最大值，返回最大值跟极限max值
                result = [closest[closest.length - 1], { [_attr]: lineEditor.maxOffset[_attr] }];
            } else { // 否则就返回相邻的两条线的值
                result = [closest[index - 1], closest[index]];
            }

            return result;
        },
        // getLineDistance(line1, line2, attr) {
        //     let spacing = nearLine[1][attr] - nearLine[0][attr];
        //     lineEditor.currentLine.style[lineEditor.isRowLine ? 'width' : 'height'] = spacing + 'px';
        //     lineEditor.currentLine.style[attr] = nearLine[0][attr] + 'px';
        // },
        /**
         * 检测与传入元素相交的所有辅助线
         * 如果没有的话就返回极限值
         * @param {*} element
         * @returns {Array}
         */
        checkAllIntersect(element) {
            const needCheck = element.type === 'row' ? '.col_line' : '.row_line',
                    _attr = element.type === 'row' ? 'left' : 'top',
                    _subAttr = element.type === 'row' ? 'offsetLeft' : 'offsetTop';
            let intersect = [];

            document.querySelectorAll(needCheck).forEach(function (v) {
                Utils.checkOverlap(element, v) && intersect.push({
                    element: v,
                    [_attr]: v[_subAttr],
                    type: v.type
                });
            })


            // 设置极限值
            if (intersect.length === 0) {
                intersect = [{ [_attr]: 0 }, { [_attr]: lineEditor.maxOffset[_attr] }];
            } else if (intersect.length === 1) {
                intersect = intersect[0][_attr] >= (lineEditor.maxOffset[_attr] / 2) ?
                    [intersect[0], { [_attr]: lineEditor.maxOffset[_attr] }] :
                    [{ [_attr]: 0 }, intersect[0]];
            }

            return intersect;
        },
    },

}
lineEditor.init();
//#endregion  ----------------------- 辅助线拖拽功能结束
